/******************************************************************************
 * @file     main.c
 * @brief    Demonstrate how to implement a USB dual virtual com port device.
 * @version  2.0.0
 * @date     17, Dec, 2014
 *
 * @note
 * Copyright (C) 2014 Nuvoton Technology Corp. All rights reserved.
 ******************************************************************************/
#include <stdio.h>
#include <string.h>
#include "Nano100Series.h"
#include "common.h"
#include "Config.h"
#include "proximity_sensor.h"
#include "UsbTransfer.h"
#include "Input.h"
#include "EventQueue.h"
#include "Timer1.h"

uint8_t status_3d=MODE_2D;
uint8_t status_3d_to_set=MODE_2D;
uint8_t is_video_on = 0;

/*---------------------------------------------------------------------------------------------------------*/
void SYS_Init(void)
{
	SYS_UnlockReg();

	CLK_EnableXtalRC(CLK_PWRCTL_HXT_EN_Msk);
	CLK_EnablePLL(CLK_PLLCTL_PLL_SRC_HXT, 96000000);
	CLK_WaitClockReady(CLK_CLKSTATUS_HXT_STB_Msk | CLK_CLKSTATUS_PLL_STB_Msk);
	CLK_SetHCLK(CLK_CLKSEL0_HCLK_S_PLL, CLK_HCLK_CLK_DIVIDER(3));
	SystemCoreClockUpdate();

	/* UART 0 */
	CLK_SetModuleClock(UART0_MODULE, CLK_CLKSEL1_UART_S_HXT, CLK_UART_CLK_DIVIDER(1));
	CLK_EnableModuleClock(UART0_MODULE);
	SYS->PB_L_MFP &= ~(SYS_PB_L_MFP_PB0_MFP_Msk | SYS_PB_L_MFP_PB1_MFP_Msk);
	SYS->PB_L_MFP |= (SYS_PB_L_MFP_PB0_MFP_UART0_RX | SYS_PB_L_MFP_PB1_MFP_UART0_TX);

	/* I2C0 */
	CLK_SetModuleClock(I2C0_MODULE, 0, 0);
	CLK_EnableModuleClock(I2C0_MODULE);
	SYS->PA_L_MFP &= ~(SYS_PA_L_MFP_PA5_MFP_Msk | SYS_PA_L_MFP_PA4_MFP_Msk);
	SYS->PA_L_MFP |= (SYS_PA_L_MFP_PA5_MFP_I2C0_SCL | SYS_PA_L_MFP_PA4_MFP_I2C0_SDA);

	/* I2C1 */
	CLK_SetModuleClock(I2C1_MODULE, 0, 0);
	CLK_EnableModuleClock(I2C1_MODULE);
	SYS->PA_H_MFP &= ~(SYS_PA_H_MFP_PA11_MFP_Msk | SYS_PA_H_MFP_PA10_MFP_Msk);
	SYS->PA_H_MFP |= (SYS_PA_H_MFP_PA11_MFP_I2C1_SCL | SYS_PA_H_MFP_PA10_MFP_I2C1_SDA);

	/* SPI1 */
	CLK_SetModuleClock(SPI1_MODULE, CLK_CLKSEL2_SPI1_S_HCLK, 0);
	CLK_EnableModuleClock(SPI1_MODULE);
	SYS->PC_H_MFP &= ~(SYS_PC_H_MFP_PC10_MFP_Msk | SYS_PC_H_MFP_PC11_MFP_Msk | SYS_PC_H_MFP_PC9_MFP_Msk);
	SYS->PC_H_MFP |= (SYS_PC_H_MFP_PC10_MFP_SPI1_MISO0 | SYS_PC_H_MFP_PC11_MFP_SPI1_MOSI0| SYS_PC_H_MFP_PC9_MFP_SPI1_SCLK);
	SYS->PC_H_MFP &= ~SYS_PC_H_MFP_PC8_MFP_Msk;
	SYS->PC_H_MFP |= SYS_PC_H_MFP_PC8_MFP_SPI1_SS0;
	SYS->PB_H_MFP &= ~SYS_PB_H_MFP_PB9_MFP_Msk;
	SYS->PB_H_MFP |= SYS_PB_H_MFP_PB9_MFP_SPI1_SS1;

	/* TIMER1 for motion sensor and proximity sensor */
	CLK_EnableModuleClock(TMR1_MODULE);
	CLK_SetModuleClock(TMR1_MODULE, CLK_CLKSEL1_TMR1_S_HXT, 0);

	/* USB */
	CLK_SetModuleClock(USBD_MODULE, 0, CLK_USB_CLK_DIVIDER(2));
	CLK_EnableModuleClock(USBD_MODULE);

	/* Audio Amp */
	GPIO_SetMode(PA, BIT14, GPIO_PMD_OUTPUT);

	SYS_LockReg();
}

void key_init()
{
    GPIO_SetMode(PC, BIT0, GPIO_PMD_INPUT);
    GPIO_ENABLE_PULL_UP(PC, BIT0);

    GPIO_SetMode(PE, BIT5, GPIO_PMD_INPUT);
    GPIO_ENABLE_PULL_UP(PE, BIT5);
}

int32_t main (void)
{
	int key_bright_count = 0;
	int count_delay=0;
	int bright_delta = 12;
	enum proximity_sensor_state state;
	
    SYS_Init();
	UART_Open(UART0, 115200);
	info("\nHighglass HMD power on ...\n");
	
	hdmi_audio_disable();
	
	HgConfigInit();

	EventQueueInit(&hmd_event_queue, &(hmd_events[0]), HMD_EVENT_SIZE);
	UsbTransferInit();

	GPIO_SetMode(PB, BIT14, GPIO_PMD_OUTPUT);
	GPIO_SetMode(PB, BIT13, GPIO_PMD_OUTPUT);
	GPIO_SetMode(PA, BIT9, GPIO_PMD_OUTPUT);
	GPIO_SetMode(PA, BIT14, GPIO_PMD_OUTPUT);
	GPIO_SetMode(PC, BIT6, GPIO_PMD_OUTPUT);

	GPIO_SetMode(PB, BIT2, GPIO_PMD_OUTPUT);
	GPIO_SetMode(PB, BIT6, GPIO_PMD_OUTPUT);

	sensor_init();

	proximity_sensor_init();

	SPI_init();
	CLK_SysTickDelay(3000);
//	PD14=0;
//	PD13=1;
	PB2=1;
	PB14=1;	
	PA9=0;	
	PB13=0;//oled 10v
	CLK_SysTickDelay(300);	
	PA9=1;
	PC6=1;
	CLK_SysTickDelay(300);
	PC6=0;	//hdmi reset	
	LVDS_i2c_init();
	PA14=0;
	
	i2c_init();
	//init_hdmi2mipi();

//	is_video_on = 0;
//	HDMI_init();
//	is_video_on = 1;
	key_init();

	USBD_Start();
	Timer1Open();

	while(1)
		{
			// handle USB event
			UsbTransferHandleEvent();

			// update sensor
			if (Timer1IsTrigger()) {
				Timer1ResetFlag();
				UsbTransferHandleSensorUpdate();
			}

			// proximity check
			if(count_delay++>20)
				{
					state = proximity_sensor_get_state();
					if (state == PROXIMITY_SENSOR_STATE_CLOSE) {
						struct contrast tContrast;
						tContrast.w = 0;
						tContrast.r = tHgConfig.tContrast.r;
						tContrast.g = tHgConfig.tContrast.g;
						tContrast.b = tHgConfig.tContrast.b;
						//info("PROXIMITY_SENSOR_STATE_CLOSE\n");
						//info("NNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNNN\n");
						count_delay=0;
						if (is_video_on == 0) {
							hdmi_video_start();
							//CLK_SysTickDelay(10000);
							SetContrast(&tContrast);
							oled_start();
							for (; tContrast.w <=tHgConfig.tContrast.w; tContrast.w++) {
								SetContrast(&tContrast);
								CLK_SysTickDelay(3 * 1000);
							}
							is_video_on = 1;
						}
					} else {
						
						//info("PROXIMITY_SENSOR_STATE_LEAVE\n");
						//info("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF\n");
						if (is_video_on &&count_delay>1500) {
							struct contrast tContrast;
							tContrast.w = tHgConfig.tContrast.w;
							tContrast.r = tHgConfig.tContrast.r;
							tContrast.g = tHgConfig.tContrast.g;
							tContrast.b = tHgConfig.tContrast.b;
							is_video_on = 0;
							for (; tContrast.w > 0; tContrast.w--) {
								SetContrast(&tContrast);
								CLK_SysTickDelay(1 * 1000);
							}
							oled_stop();
							hdmi_video_stop();
							
						}
					}

				}

			if (is_video_on) {
				// 3d mode cmd check
				if (status_3d != status_3d_to_set) {
					if (status_3d_to_set == MODE_2D) {
						Switch_3D(0);
						status_3d = MODE_2D;
					} else if (status_3d_to_set == MODE_3D_FULL) {
						Switch_3D(1);
						status_3d = MODE_3D_FULL;
					}
				}

				// 3d mode key check
				if (PE5 == 0) {
					long time_count = 0;
					while (PE5 == 0) {
						time_count++;
						CLK_SysTickDelay(30000);
						if (time_count > 50) {
							if (status_3d == MODE_2D) {
								Switch_3D_fast(1);
								status_3d = MODE_3D_HALF;
								status_3d_to_set = MODE_3D_HALF;
							} else if (status_3d == MODE_3D_FULL) {
								Switch_3D(0);
								status_3d = MODE_2D;
								status_3d_to_set = MODE_2D;
							} else {
								Switch_3D_fast(0);
								status_3d = MODE_2D;
								status_3d_to_set = MODE_2D;
							}
						}
					}
					
					if (time_count > 50) {   
					} else {
						if(status_3d == MODE_2D) {
							Switch_3D(1);
							status_3d = MODE_3D_FULL;
							status_3d_to_set = MODE_3D_FULL;
						} else {
							Switch_3D(0);
							status_3d = MODE_2D;
							status_3d_to_set = MODE_2D;
						}
					}
				}

				// brightness key check
				if (PC0 == 0) {
					// debounce
					CLK_SysTickDelay(1000);
					if (PC0 == 0) {
						if (key_bright_count >= 10) {
							tHgConfig.tBrightness.w += bright_delta;
							if (bright_delta > 0) {
								InputReportKeyAuto(&hmd_event_queue, KEY_BRIGHTNESSUP);
							} else {
								InputReportKeyAuto(&hmd_event_queue, KEY_BRIGHTNESSDOWN);
							}
							
							if (tHgConfig.tBrightness.w >= BRIGHTNESS_MAX) {
								tHgConfig.tBrightness.w = BRIGHTNESS_MAX;
								bright_delta = -12;
							} else if (tHgConfig.tBrightness.w <= BRIGHTNESS_MIN) {
								tHgConfig.tBrightness.w = BRIGHTNESS_MIN;
								bright_delta = 12;
							}
							SetBrightness(&tHgConfig.tBrightness);
							HgConfigWrite(&tHgConfig);
							
							key_bright_count = -10000000;
							info("on key bright, tHgConfig.tBrightness.w : %u\n",
								tHgConfig.tBrightness.w);
						} else {
							key_bright_count++;
						}
					}
				} else {
					key_bright_count = 0;
				}
			}

			// hdmi plug in and out check
			hdmi_monitor();
		}
}



/*** (C) COPYRIGHT 2013 Nuvoton Technology Corp. ***/

